package com.cq.hd.admin.controller;

import com.cq.hd.admin.context.ApplicationContextHolder;
import com.cq.hd.admin.dto.AdminRoleUpdateDto;
import com.cq.hd.admin.po.TbAdminPermissionPo;
import com.cq.hd.admin.utils.PermissionUtil;
import com.cq.hd.admin.annotation.RequiresPermissionsDesc;
import com.cq.hd.admin.dto.AdminRoleCreateDto;
import com.cq.hd.admin.dto.AdminRoleDto;
import com.cq.hd.admin.po.TbAdminRolePo;
import com.cq.hd.admin.service.TbAdminPermissionService;
import com.cq.hd.admin.service.TbAdminRoleService;
import com.cq.hd.admin.utils.Permission;
import com.cq.hd.admin.vo.AdminRoleVo;
import com.cq.hd.admin.vo.PermVo;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.ResultGenerator;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author mYunYu
 * @since 2021-10-28
 */

@Api(tags = "角色相关接口")
@Slf4j
@RestController
@RequestMapping("/role")
public class TbAdminRoleController extends BaseController {

    private TbAdminRoleService adminRoleService;

    @Autowired
    public void setAdminRoleService(TbAdminRoleService adminRoleService) {
        this.adminRoleService = adminRoleService;
    }

    private TbAdminPermissionService adminPermissionService;

    @Autowired
    public void setAdminPermissionService(TbAdminPermissionService adminPermissionService) {
        this.adminPermissionService = adminPermissionService;
    }

    private List<PermVo> systemPermissions = null;
    private Set<String> systemPermissionsString = null;

    @ApiOperation(value = "角色管理列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "角色名称", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "pageNum", value = "当前页", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", paramType = "query", dataType = "int")
    })
    @PostMapping("/list/more")
    @RequiresPermissions("admin:role:list")
    @RequiresPermissionsDesc(menu = {"系统管理", "角色管理"}, button = "查询")
    public Object list(String name, @RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
                       @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        try {
            Page<AdminRoleVo> pageResult = adminRoleService.getAdminRoleList(name, pageNum, pageSize);
            return ResultGenerator.success(pageResult);
        } catch (Exception e) {
            log.error("获取角色列表接口（/role/list/more）异常");
            return ResultGenerator.error("获取角色列表失败");
        }
    }

    @ApiOperation(value = "编辑角色")
    @PostMapping("/update")
    @RequiresPermissions("admin:role:update")
    @RequiresPermissionsDesc(menu = {"系统管理", "角色管理"}, button = "编辑")
    public Object update(@RequestBody AdminRoleUpdateDto adminRoleUpdateDto) {
        String name = adminRoleUpdateDto.getName();
        if (StringUtils.isEmpty(name)) {
            return ResultGenerator.error("角色名称不能为空");
        }

        if (name.length() > 10) {
            return ResultGenerator.error("角色名称最多支持输入10个字");
        }

        String remark = adminRoleUpdateDto.getRemark();
        if(!StringUtils.isEmpty(remark) && remark.length() > 50){
            return ResultGenerator.error("备注最多支持输入10个字");
        }

        AdminRoleDto adminRole = new AdminRoleDto();
        BeanUtils.copyProperties(adminRoleUpdateDto, adminRole);
        adminRoleService.updateAdminRoleById(adminRole);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "删除角色")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "角色ID", required = true, paramType = "path", dataType = "int")
    })
    @PostMapping("/delete/{id}")
    @RequiresPermissions("admin:role:delete")
    @RequiresPermissionsDesc(menu = {"系统管理", "角色管理"}, button = "删除")
    public Object delete(@PathVariable("id") Integer id) {
        if (id == null) {
            return ResultGenerator.error("参数异常");
        }

        return adminRoleService.deleteRoleById(id);
    }

    /**
     * 管理员的权限情况
     *
     * @return 系统所有权限列表和管理员已分配权限
     */
    @ApiOperation(value = "管理员权限获取")
    @GetMapping("/permissions")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, paramType = "query", dataType = "int")
    })
    @RequiresPermissions("admin:role:permission:get")
    @RequiresPermissionsDesc(menu = {"系统管理", "角色管理"}, button = "授权")
    public Object getPermissions(Integer roleId) {
        List<PermVo> systemPermissions = getSystemPermissions();
        Set<String> assignedPermissions = getAssignedPermissions(roleId);

        Map<String, Object> data = new HashMap<>();
        data.put("systemPermissions", systemPermissions);
        data.put("assignedPermissions", assignedPermissions);
        return ResultGenerator.success(data);
    }

    private List<PermVo> getSystemPermissions() {
        final String basicPackage = "com.cq.hd.admin";
        if (systemPermissions == null) {
            List<Permission> permissions = PermissionUtil.listPermission(ApplicationContextHolder.getApplicationContext(), basicPackage);
            systemPermissions = PermissionUtil.listPermVo(permissions);
            systemPermissionsString = PermissionUtil.listPermissionString(permissions);
        }
        return systemPermissions;
    }

    private Set<String> getAssignedPermissions(Integer roleId) {
        Set<String> assignedPermissions = null;
        if (adminPermissionService.checkSuperPermission(roleId)) {
            getSystemPermissions();
            assignedPermissions = systemPermissionsString;
        } else {
            assignedPermissions = adminPermissionService.getSetPermissionByRoleId(roleId);
        }

        return assignedPermissions;
    }

    @ApiOperation(value = "管理员权限变更")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, paramType = "query", dataType = "int")
    })
    @PostMapping("/permissions/update")
    @RequiresPermissions("admin:role:permission:update")
    @RequiresPermissionsDesc(menu = {"系统管理", "角色管理"}, button = "管理员权限变更")
    public Object updatePermissions(@RequestParam(required = true) Integer roleId,
                                    @RequestParam(value = "permissionList", required = true) @ApiParam(value = "权限列表") List<String> permissionList) {
        if (roleId == null || permissionList == null) {
            return ResultGenerator.error("参数异常");
        }

        // 如果修改的角色是超级权限，则拒绝修改。
        if (adminPermissionService.checkSuperPermission(roleId)) {
            return ResultGenerator.error("当前角色的超级权限不能变更!");
        }

        // 先删除旧的权限，再更新新的权限
        adminPermissionService.deleteByRoleId(roleId);
        for (String permission : permissionList) {
            TbAdminPermissionPo newPermission = new TbAdminPermissionPo();
            newPermission.setRoleId(roleId);
            newPermission.setPermission(permission);
            adminPermissionService.addPermission(newPermission);
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "获取管理员角色列表")
    @GetMapping("/options")
    public Object options() {
        List<TbAdminRolePo> roleList = adminRoleService.getAllRole();
        List<Map<String, Object>> options = new ArrayList<>(roleList.size());
        for (TbAdminRolePo role : roleList) {
            Map<String, Object> option = new HashMap<>(2);
            option.put("value", role.getId());
            option.put("label", role.getName());
            options.add(option);
        }
        return ResultGenerator.success(options);
    }


    @ApiOperation(value = "新增角色")
    @PostMapping("/create")
    @RequiresPermissions("admin:role:create")
    @RequiresPermissionsDesc(menu = {"系统管理", "角色管理"}, button = "添加")
    public Object create(@RequestBody AdminRoleCreateDto adminRoleCreateDto) {
        String name = adminRoleCreateDto.getName();
        if (StringUtils.isEmpty(name)) {
            return ResultGenerator.error("参数异常");
        }

        if (name.length() > 10) {
            return ResultGenerator.error("角色名称最多支持输入10个字");
        }

        String remark = adminRoleCreateDto.getRemark();
        if(!StringUtils.isEmpty(remark) && remark.length() > 50){
            return ResultGenerator.error("备注最多支持输入10个字");
        }

        if (adminRoleService.checkExist(adminRoleCreateDto.getName())) {
            return ResultGenerator.error("角色已经存在");
        }
        AdminRoleDto adminRoleDto = new AdminRoleDto();
        BeanUtils.copyProperties(adminRoleCreateDto, adminRoleDto);
        adminRoleService.addRole(adminRoleDto);
        return ResultGenerator.success(adminRoleDto);
    }

}
